﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using Enter.Common.statics;
using Enter.Common.internals;

namespace Enter.Common.Upload
{
	public sealed class Watermark
	{
		#region 私有属性
		private WaterMarkPositionType _typePosition = WaterMarkPositionType.BOTTOM_RIGHT;


		private WaterMarkType _type = WaterMarkType.IMAGE;


		private string _watermarkText = string.Empty;


		private string _watermarkImage = string.Empty;


		private float _alpha = 0.3f;

		#endregion

		#region 属性

		/// <summary>
		/// 水印位置
		/// </summary>
		public WaterMarkPositionType TypePosition
		{
			get { return _typePosition; }
			set { _typePosition = value; }
		}
		/// <summary>
		/// 水印类型
		/// </summary>
		public WaterMarkType MarkType
		{
			get { return _type; }
			set { _type = value; }
		}
		/// <summary>
		/// 水印文字
		/// </summary>
		public string WatermarkText
		{
			get { return _watermarkText; }
			set { _watermarkText = value; }
		}

		/// <summary>
		/// 水印图片 绝对地址
		/// </summary>
		public string WatermarkImage
		{
			get { return _watermarkImage; }
			set { _watermarkImage = value; }
		}

		/// <summary>
		/// 透明度(0.1-1.0数值越小透明度越高)
		/// </summary>
		public float Alpha
		{
			get { return _alpha; }
			set
			{
				_alpha = value;
				if ((_alpha > 1.0f) || (_alpha < 0.1f))
				{
					_alpha = 0.3f;
				}
			}
		}


		#endregion

		#region 枚举

		public enum WaterMarkType
		{
			IMAGE,
			TEXT
		}

		public enum WaterMarkPositionType
		{
			TOP_LEFT,
			TOP_RIGHT,
			BOTTOM_RIGHT,
			BOTTOM_LEFT
		}

		#endregion


		public Watermark()
		{

		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="type">水印类型</param>
		/// <param name="typePosition">水印位置</param>
		/// <param name="value">值</param>
		public Watermark(WaterMarkType type, WaterMarkPositionType typePosition, string value)
		{
			this._type = type;
			this._typePosition = typePosition;
			if (_type == WaterMarkType.TEXT)
			{
				this._watermarkText = value;
			}
			else
			{
				this._watermarkImage = value;
			}
		}

		/// <summary>
		/// 添加水印
		/// </summary>
		/// <param name="oldpath">原图片地址</param>
		/// <param name="newpath">新图片地址</param>
		public void AddWaterMark(string oldpath, string newpath)
		{
			this.AddWaterMark(oldpath, newpath, this._type);
		}

		/// <summary>
		/// 添加水印
		/// </summary>
		/// <param name="oldpath">原图片地址</param>
		/// <param name="newpath">新图片地址</param>
		/// <param name="type">水印类型</param>
		public void AddWaterMark(string oldpath, string newpath, WaterMarkType type)
		{
			this.addWaterMark(oldpath, newpath, type);
		}

		private void addWaterMark(string oldpath, string newpath, WaterMarkType type)
		{

			string fileSourceExtension = FilesStatic.GetExtension(oldpath).ToLower();
			if (!FilesStatic.IsFile(oldpath))
			{
				return;
			}
			if (FilesStatic.IsFile(newpath))
			{
				FilesStatic.DelFile(newpath);
			}
			if (type == WaterMarkType.IMAGE)
			{
				if (!FilesStatic.IsFile(this._watermarkImage))
				{
					return;
				}
				string fileExtension = FilesStatic.GetExtension(this._watermarkImage).ToLower();
				if (!SafeCheck.IsJPGstr(fileExtension))
				{
					return;
				}
			}
			if (SafeCheck.IsJPGstr(fileSourceExtension))
			{
				try
				{
					// 将需要加上水印的图片装载到Image对象中
					System.Drawing.Image image = System.Drawing.Image.FromFile(oldpath);
					// 封装 GDI+ 位图，此位图由图形图像及其属性的像素数据组成。
					Bitmap b = new Bitmap(image.Width, image.Height, PixelFormat.Format24bppRgb);
					// 设定分辨率
					//?? b.SetResolution(image.HorizontalResolution, image.VerticalResolution);
					// 定义一个绘图画面用来装载位图
					Graphics g = Graphics.FromImage(b);
					g.Clear(Color.White);

					//SmoothingMode：指定是否将平滑处理（消除锯齿）应用于直线、曲线和已填充区域的边缘。
					// 成员名称   说明 
					// AntiAlias      指定消除锯齿的呈现。  
					// Default        指定不消除锯齿。  
					// HighQuality  指定高质量、低速度呈现。  
					// HighSpeed   指定高速度、低质量呈现。  
					// Invalid        指定一个无效模式。  
					// None          指定不消除锯齿。
					g.SmoothingMode = SmoothingMode.HighQuality;
					g.InterpolationMode = InterpolationMode.High;

					//将我们要添加水印的图片按照原始大小描绘（复制）到图形中
					g.DrawImage(image, 0, 0, image.Width, image.Height);


					////将我们要添加水印的图片按照原始大小描绘（复制）到图形中
					//g.DrawImage(
					// image,                                           //   要添加水印的图片
					// new Rectangle(0, 0, image.Width, image.Height), //  根据要添加的水印图片的宽和高
					// 0,                                                     //  X方向从0点开始描绘
					// 0,                                                     // Y方向 
					// phWidth,                                            //  X方向描绘长度
					// phHeight,                                           //  Y方向描绘长度
					// GraphicsUnit.Pixel);                              // 描绘的单位，这里用的是像素

					switch (type)
					{
						//是图片的话               
						case WaterMarkType.IMAGE:
							this.addWatermarkImage(g, _watermarkImage, this._typePosition, image.Width, image.Height);
							break;
						//如果是文字                    
						case WaterMarkType.TEXT:
							this.addWatermarkText(g, _watermarkText, this._typePosition, image.Width, image.Height);
							break;
					}
					//将grPhoto保存

					ImageCodecInfo icf = ImageHelper.GetImageCodecInfo(ImageFormat.Jpeg);
					ImageHelper.SaveImage(b, newpath, icf);
					// b.Save(newpath);
					b.Dispose();
					image.Dispose();
				}
				catch
				{

					//if (File.Exists(oldpath))
					//{
					//    File.Delete(oldpath);
					//}
				}
				finally
				{

					//if (File.Exists(oldpath))
					//{
					//    File.Delete(oldpath);
					//}


				}
			}

		}


		/// <summary>
		/// 添加文字水印
		/// </summary>
		/// <param name="picture">imge 对象</param>
		/// <param name="_watermarkText">文字</param>
		/// <param name="_watermarkPosition">水印位置</param>
		/// <param name="_width">图片宽</param>
		/// <param name="_height">图片高</param>
		private void addWatermarkText(Graphics picture, string watermarkText, WaterMarkPositionType typePosition, int _width, int _height)
		{
			//根据图片的大小我们来确定添加上去的文字的大小
			//在这里我们定义一个数组来确定
			int[] sizes = new int[] { 16, 14, 12, 10, 8, 6, 4 };
			//字体
			Font crFont = null;
			//矩形的宽度和高度，SizeF有三个属性，分别为Height高，width宽，IsEmpty是否为空
			SizeF crSize = new SizeF();

			//利用一个循环语句来选择我们要添加文字的型号
			//直到它的长度比图片的宽度小
			for (int i = 0; i < 7; i++)
			{
				crFont = new Font("arial", sizes[i], FontStyle.Bold);

				//测量用指定的 Font 对象绘制并用指定的 StringFormat 对象格式化的指定字符串。
				crSize = picture.MeasureString(watermarkText, crFont);

				// ushort 关键字表示一种整数数据类型
				if ((ushort)crSize.Width < (ushort)_width)
					break;
			}

			float xpos = 0;
			float ypos = 0;
			switch (typePosition)
			{
				case WaterMarkPositionType.TOP_LEFT:
					xpos = ((float)_width * (float).01) + (crSize.Width / 2);
					ypos = (float)_height * (float).01;
					break;
				case WaterMarkPositionType.TOP_RIGHT:
					xpos = ((float)_width * (float).99) - (crSize.Width / 2);
					ypos = (float)_height * (float).01;
					break;
				case WaterMarkPositionType.BOTTOM_LEFT:
					xpos = ((float)_width * (float).01) + (crSize.Width / 2);
					ypos = ((float)_height * (float).99) - crSize.Height;
					break;
				case WaterMarkPositionType.BOTTOM_RIGHT:
					xpos = ((float)_width * (float).99) - (crSize.Width / 2);
					ypos = ((float)_height * (float).99) - crSize.Height;
					break;
			}

			//封装文本布局信息（如对齐、文字方向和 Tab 停靠位），显示操作（如省略号插入和国家标准 (National) 数字替换）和 OpenType 功能。
			StringFormat StrFormat = new StringFormat();

			//定义需要印的文字居中对齐
			StrFormat.Alignment = StringAlignment.Center;

			//SolidBrush:定义单色画笔。画笔用于填充图形形状，如矩形、椭圆、扇形、多边形和封闭路径。
			//这个画笔为描绘阴影的画笔，呈灰色
			int m_alpha = Convert.ToInt32(256 * _alpha);
			SolidBrush semiTransBrush2 = new SolidBrush(Color.FromArgb(m_alpha, 0, 0, 0));

			//描绘文字信息，这个图层向右和向下偏移一个像素，表示阴影效果
			//DrawString 在指定矩形并且用指定的 Brush 和 Font 对象绘制指定的文本字符串。
			picture.DrawString(_watermarkText, crFont, semiTransBrush2, xpos + 1, ypos + 1, StrFormat);

			//从四个 ARGB 分量（alpha、红色、绿色和蓝色）值创建 Color 结构，这里设置透明度为153
			//这个画笔为描绘正式文字的笔刷，呈白色
			SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(153, 255, 255, 255));
			//第二次绘制这个图形，建立在第一次描绘的基础上
			picture.DrawString(_watermarkText, crFont, semiTransBrush, xpos, ypos, StrFormat);

			//释放资源，将定义的Graphics实例grPhoto释放，grPhoto功德圆满
			semiTransBrush2.Dispose();
			semiTransBrush.Dispose();



		}


		/// <summary>
		/// 添加图片水印
		/// </summary>
		/// <param name="picture">imge 对象</param>
		/// <param name="WaterMarkPicPath">图片地址</param>
		/// <param name="typePosition">水印位置</param>
		/// <param name="_width">图片宽</param>
		/// <param name="_height">图片高</param>
		private void addWatermarkImage(Graphics picture, string WaterMarkPicPath, WaterMarkPositionType typePosition, int _width, int _height)
		{
			//同样，由于水印是图片，我们也需要定义一个Image来装载它
			Image watermark1 = new Bitmap(WaterMarkPicPath);




			//ImageAttributes 对象包含有关在呈现时如何操作位图和图元文件颜色的信息。
			ImageAttributes imageAttributes = new ImageAttributes();

			//Colormap: 定义转换颜色的映射
			ColorMap colorMap = new ColorMap();

			//我的水印图被定义成拥有绿色背景色的图片被替换成透明
			colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
			colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);

			ColorMap[] remapTable = { colorMap };

			imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);

			float[][] colorMatrixElements = {
                                                new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},  // red红色
                                                new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},//green绿色
                                                new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},//blue蓝色       
                                                new float[] {0.0f,  0.0f,  0.0f,  _alpha, 0.0f},//透明度     
                                                new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}//
                                            };

			//  ColorMatrix:定义包含 RGBA 空间坐标的 5 x 5 矩阵。

			ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);

			//  ImageAttributes 类的若干方法通过使用颜色矩阵调整图像颜色。
			imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

			int xpos = 0;
			int ypos = 0;
			int WatermarkWidth = 0;
			int WatermarkHeight = 0;
			double bl = 1d;
			//计算水印图片的比率
			//取背景的1/4宽度来比较
			if ((_width > watermark1.Width * 4) && (_height > watermark1.Height * 4))
			{
				bl = 1;
			}
			else if ((_width > watermark1.Width * 4) && (_height < watermark1.Height * 4))
			{
				bl = Convert.ToDouble(_height / 4) / Convert.ToDouble(watermark1.Height);

			}
			else

				if ((_width < watermark1.Width * 4) && (_height > watermark1.Height * 4))
				{
					bl = Convert.ToDouble(_width / 4) / Convert.ToDouble(watermark1.Width);
				}
				else
				{
					if ((_width * watermark1.Height) > (_height * watermark1.Width))
					{
						bl = Convert.ToDouble(_height / 4) / Convert.ToDouble(watermark1.Height);

					}
					else
					{
						bl = Convert.ToDouble(_width / 4) / Convert.ToDouble(watermark1.Width);

					}

				}

			WatermarkWidth = Convert.ToInt32(watermark1.Width * bl);
			WatermarkHeight = Convert.ToInt32(watermark1.Height * bl);



			switch (typePosition)
			{
				case WaterMarkPositionType.TOP_LEFT:
					xpos = 10;
					ypos = 10;
					break;
				case WaterMarkPositionType.TOP_RIGHT:
					xpos = _width - WatermarkWidth - 10;
					ypos = 10;
					break;
				case WaterMarkPositionType.BOTTOM_LEFT:
					xpos = 10;
					ypos = _height - WatermarkHeight - 10;
					break;

				case WaterMarkPositionType.BOTTOM_RIGHT:
					xpos = _width - WatermarkWidth - 10;
					ypos = _height - WatermarkHeight - 10;
					break;
			}

			picture.DrawImage(watermark1, new Rectangle(xpos, ypos, WatermarkWidth, WatermarkHeight), 0, 0, watermark1.Width, watermark1.Height, GraphicsUnit.Pixel, imageAttributes);
			watermark1.Dispose();
			imageAttributes.Dispose();
		}

	}
}
